<template>
  <div class="file-tree-node">
    <div 
      :class="[
        'node-content',
        { 
          'is-folder': node.type === 'folder',
          'is-file': node.type === 'file',
          'is-selected': isSelected,
          'is-expanded': isExpanded
        }
      ]"
      @click="handleClick"
      @contextmenu="handleContextMenu"
    >
      <!-- Indentation -->
      <div class="node-indent" :style="{ width: `${depth * 20}px` }"></div>
      
      <!-- Expand/Collapse Icon -->
      <div class="node-icon" @click.stop="handleToggleFolder">
        <el-icon v-if="node.type === 'folder'" class="folder-icon">
          <component :is="isExpanded ? FolderOpened : Folder" />
        </el-icon>
        <el-icon v-else class="file-icon">
          <Document />
        </el-icon>
      </div>
      
      <!-- Checkbox -->
      <el-checkbox
        v-if="node.type === 'file'"
        :model-value="isSelected"
        @change="handleSelectionChange"
        @click.stop
        size="small"
      />
      
      <!-- Node Label -->
      <div class="node-label" :title="node.path">
        <span class="node-name">{{ node.name }}</span>
        <div v-if="node.type === 'file'" class="node-meta">
          <el-text size="small" type="info">
            {{ formatFileSize(node.size) }}
          </el-text>
          <el-text size="small" type="info">
            {{ formatDate(node.timestamp) }}
          </el-text>
        </div>
      </div>
      
      <!-- Actions -->
      <div class="node-actions" v-if="node.type === 'file'">
        <el-button-group size="small">
          <el-tooltip content="查看信息">
            <el-button 
              :icon="InfoFilled" 
              @click.stop="$emit('showFileInfo', node)"
              text
            />
          </el-tooltip>
          <el-tooltip content="查看历史">
            <el-button 
              :icon="Clock" 
              @click.stop="$emit('showFileHistory', node)"
              text
            />
          </el-tooltip>
          <el-tooltip content="预览内容">
            <el-button 
              :icon="View" 
              @click.stop="$emit('previewFile', node)"
              text
            />
          </el-tooltip>
        </el-button-group>
      </div>
    </div>
    
    <!-- Children with lazy loading -->
    <div v-if="node.type === 'folder' && isExpanded" class="node-children">
      <!-- Use virtual scrolling for large folders -->
      <VirtualScrollList
        v-if="shouldUseVirtualScroll"
        :items="flattenedChildren"
        :item-height="32"
        :container-height="Math.min(flattenedChildren.length * 32, 300)"
        @load-more="loadMoreChildren"
      >
        <template #default="{ item }">
          <FileTreeNode
            :node="item as any"
            :depth="depth + 1"
            :selected-files="selectedFiles"
            :expanded-folders="expandedFolders"
            @toggle-selection="$emit('toggleSelection', $event)"
            @toggle-folder="$emit('toggleFolder', $event)"
            @show-file-info="$emit('showFileInfo', $event)"
            @show-file-history="$emit('showFileHistory', $event)"
            @preview-file="$emit('previewFile', $event)"
          />
        </template>
      </VirtualScrollList>
      
      <!-- Regular rendering for small folders -->
      <template v-else>
        <FileTreeNode
          v-for="child in visibleChildren"
          :key="child.id"
          :node="child"
          :depth="depth + 1"
          :selected-files="selectedFiles"
          :expanded-folders="expandedFolders"
          @toggle-selection="$emit('toggleSelection', $event)"
          @toggle-folder="$emit('toggleFolder', $event)"
          @show-file-info="$emit('showFileInfo', $event)"
          @show-file-history="$emit('showFileHistory', $event)"
          @preview-file="$emit('previewFile', $event)"
        />
      </template>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue'
import { 
  Folder, 
  FolderOpened, 
  Document, 
  InfoFilled, 
  Clock, 
  View 
} from '@element-plus/icons-vue'
import VirtualScrollList from './VirtualScrollList.vue'
import type { FileTreeNode as FileTreeNodeType } from '../types/basic'

interface Props {
  node: FileTreeNodeType
  depth?: number
  selectedFiles: string[]
  expandedFolders: Set<string>
}

interface Emits {
  (e: 'toggleSelection', fileId: string): void
  (e: 'toggleFolder', folderPath: string): void
  (e: 'showFileInfo', node: FileTreeNodeType): void
  (e: 'showFileHistory', node: FileTreeNodeType): void
  (e: 'previewFile', node: FileTreeNodeType): void
}

const props = withDefaults(defineProps<Props>(), {
  depth: 0
})

const emit = defineEmits<Emits>()

// Computed properties
const isSelected = computed(() => 
  props.node.type === 'file' && props.selectedFiles.includes(props.node.id)
)

const isExpanded = computed(() => 
  props.node.type === 'folder' && props.expandedFolders.has(props.node.path)
)

// 虚拟滚动相关
const VIRTUAL_SCROLL_THRESHOLD = 100 // 超过100个子项时使用虚拟滚动
const loadedChildrenCount = ref(50) // 初始加载50个子项

const shouldUseVirtualScroll = computed(() => {
  return props.node.children && props.node.children.length > VIRTUAL_SCROLL_THRESHOLD
})

const visibleChildren = computed(() => {
  if (!props.node.children) return []
  if (shouldUseVirtualScroll.value) return []
  return props.node.children
})

const flattenedChildren = computed(() => {
  if (!props.node.children) return []
  return props.node.children.slice(0, loadedChildrenCount.value)
})

const loadMoreChildren = () => {
  if (props.node.children && loadedChildrenCount.value < props.node.children.length) {
    loadedChildrenCount.value = Math.min(
      loadedChildrenCount.value + 50,
      props.node.children.length
    )
  }
}

// Event handlers
function handleClick() {
  if (props.node.type === 'folder') {
    handleToggleFolder()
  } else {
    handleSelectionChange()
  }
}

function handleToggleFolder() {
  if (props.node.type === 'folder') {
    emit('toggleFolder', props.node.path)
  }
}

function handleSelectionChange() {
  if (props.node.type === 'file') {
    emit('toggleSelection', props.node.id)
  }
}

function handleContextMenu(event: MouseEvent) {
  event.preventDefault()
  // TODO: Implement context menu
}

// Utility functions
function formatFileSize(size?: number): string {
  if (!size) return '-'
  
  const units = ['B', 'KB', 'MB', 'GB']
  let unitIndex = 0
  let fileSize = size
  
  while (fileSize >= 1024 && unitIndex < units.length - 1) {
    fileSize /= 1024
    unitIndex++
  }
  
  return `${fileSize.toFixed(unitIndex === 0 ? 0 : 1)} ${units[unitIndex]}`
}

function formatDate(timestamp?: number): string {
  if (!timestamp) return '-'
  
  return new Date(timestamp).toLocaleString('zh-CN', {
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit'
  })
}
</script>

<style scoped>
.file-tree-node {
  user-select: none;
}

.node-content {
  display: flex;
  align-items: center;
  padding: 4px 8px;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.2s ease;
  min-height: 32px;
}

.node-content:hover {
  background-color: var(--el-color-primary-light-9);
}

.node-content.is-selected {
  background-color: var(--el-color-primary-light-8);
  border: 1px solid var(--el-color-primary-light-6);
}

.node-indent {
  flex-shrink: 0;
}

.node-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  margin-right: 8px;
  flex-shrink: 0;
}

.folder-icon {
  color: var(--el-color-warning);
  cursor: pointer;
}

.file-icon {
  color: var(--el-color-info);
}

.node-label {
  flex: 1;
  min-width: 0;
  margin-right: 8px;
}

.node-name {
  font-weight: 500;
  color: var(--el-text-color-primary);
  word-break: break-all;
}

.node-meta {
  display: flex;
  gap: 12px;
  margin-top: 2px;
}

.node-actions {
  opacity: 0;
  transition: opacity 0.2s ease;
  flex-shrink: 0;
}

.node-content:hover .node-actions {
  opacity: 1;
}

.node-children {
  margin-left: 0;
}

/* Folder specific styles */
.node-content.is-folder .node-name {
  font-weight: 600;
}

.node-content.is-expanded .folder-icon {
  color: var(--el-color-primary);
}

/* File specific styles */
.node-content.is-file {
  padding-left: 12px;
}

.node-content.is-file .node-name {
  font-weight: 400;
}

/* Selection styles */
.node-content.is-selected .node-name {
  color: var(--el-color-primary);
  font-weight: 500;
}

/* Responsive adjustments */
@media (max-width: 768px) {
  .node-meta {
    flex-direction: column;
    gap: 2px;
  }
  
  .node-actions {
    opacity: 1;
  }
}
</style>